package cn.le.crawler.jd;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.le.annotation.CrawlerName;
import cn.le.crawler.Crawler;
import cn.le.crawler.AbstractCrawler;
import cn.le.entity.CrawlerHome;
import cn.le.entity.JdData;
import cn.le.enums.EnumCrawler;
import cn.le.enums.EnumHomeStatus;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import okhttp3.Request;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutorCompletionService;
import java.util.zip.GZIPInputStream;

/**
 * @Description
 * @Author le
 * @Date 2020/3/1 11:24
 * @Version 0.1
 **/
@Component
@CrawlerName(value = EnumCrawler.Jd)
public class JdHomeCrawler extends AbstractCrawler implements Crawler {


    /**
     * 爬虫京东房源数据
     * @return
     */
    public List<CrawlerHome> crawlerHome() throws Exception {
        //启动多线程抓取房源
        CompletionService<List<JdData>> homeCs = new ExecutorCompletionService<List<JdData>>(executor);
        List<String> urls = JdPropertyUtil.getUrls();
        urls.forEach(url->{
            homeCs.submit(new Callable<List<JdData>>() {
                @Override
                public List<JdData> call() throws Exception {
                   JSONObject jsonObject = requestData(url);
                   if (jsonObject == null){
                       return null;
                   }
                   List<JdData> jdDataList = parsingData(jsonObject);
                   return jdDataList;
                }
            });
        });
        int index = 0;
        CompletionService<JdData> homeProfileCs = new ExecutorCompletionService<JdData>(executor);
        for (int i = 0,size = urls.size(); i < size; i++) {
            List<JdData> jdDataList = homeCs.take().get();
            if (CollectionUtils.isEmpty(jdDataList)){
                continue;
            }
            jdDataList.forEach(jdData -> {
                //竞拍人数
                homeProfileCs.submit(new Callable<JdData>() {
                    @Override
                    public JdData call() throws Exception {
                        competeNumber(jdData);
                        return jdData;
                    }
                });
                homeProfileCs.submit(new Callable<JdData>() {
                    @Override
                    public JdData call() throws Exception {
                        parsingHomeImg(jdData);
                        return jdData;
                    }
                });
            });
            index += jdDataList.size();
        }
        index = index * 2;
        Set<Long> ids = new HashSet<>();
        List<CrawlerHome> crawlerHomes = new LinkedList<>();
        for (int i = 0;i < index; i++){
            JdData jdData = homeProfileCs.take().get();
            CrawlerHome crawlerHome = mapperCrawlerHome(jdData);
            if (ids.contains(crawlerHome.getHomeId())){
                continue;
            }
            ids.add(crawlerHome.getHomeId());
            crawlerHomes.add(crawlerHome);
        }
        return crawlerHomes;
    }

    public static CrawlerHome mapperCrawlerHome(JdData jdData) {
        CrawlerHome crawlerHome = new CrawlerHome();
        try {
            BeanUtil.copyProperties(jdData,crawlerHome);
            String sellOff = (jdData.getPaimaiTimes().equals(1) || jdData.getPaimaiTimes().equals(2)) ? "拍卖" :
                    (jdData.getPaimaiTimes().equals(4) ? "变卖" : "其它");
            crawlerHome.setSellOff(sellOff);
            //状态
            crawlerHome.setStatus(EnumHomeStatus.JdStatus.getByCode(jdData.getAuctionStatus(),jdData.getDisplayStatus()).getText());
            //初始价格
            crawlerHome.setInitialPrice(jdData.getCurrentPrice());
            //评估价
            crawlerHome.setConsultPrice(jdData.getAssessmentPrice());
            if (crawlerHome.getConsultPrice() == null || crawlerHome.getConsultPrice() == 0){
                crawlerHome.setConsultPrice(jdData.getMarketPrice());
            }

            crawlerHome.setStartTime(jdData.getStartTimeMills());
            crawlerHome.setEndTime(jdData.getEndTimeMills());
            crawlerHome.setViewerCount(jdData.getAccessNum());
            crawlerHome.setBidCount(jdData.getAccessEnsureNum());
            crawlerHome.setHomeId(jdData.getId());
            crawlerHome.setArea(jdData.getProvince() + " " + jdData.getCity());
            crawlerHome.setCover(JdPropertyUtil.IMG_PREFIX + jdData.getProductImage());
            }catch (Exception e){
                e.printStackTrace();
            }
        return crawlerHome;
    }

    /**
     * 爬取房源图片
     * @param
     * @return
     */
    public static void parsingHomeImg(JdData jdData) throws IOException {
        JSONObject jsonObject = requestData(JdPropertyUtil.getImgUrl(jdData.getId()));
        if (jsonObject == null){
            return;
        }
        JSONObject dataJson = (JSONObject) jsonObject.get("data");
        List<Map<String,String>> paimaiImageResultList = (List<Map<String, String>>) JSON.toJSON(dataJson.get("paimaiImageResultList"));
        if (CollectionUtil.isEmpty(paimaiImageResultList)){
            return;
        }
        List<String> urls = new ArrayList<>(15);
        paimaiImageResultList.forEach(map->{
            String url = JdPropertyUtil.IMG_PREFIX + map.get("imagePath");
            urls.add(url);
        });
        String homeImgJson = JSON.toJSONString(urls);
        jdData.setHomeImgs(homeImgJson);
        //详情页
        jdData.setItemUrl(JdPropertyUtil.ITEM_URL + jdData.getId());
    }

    /**
     * 竞争人数
     * @param jdData
     */
    private static void competeNumber(JdData jdData) throws IOException {
        JSONObject jsonObject = requestData(JdPropertyUtil.getCompeteUrl(jdData.getId()));
        if (jsonObject == null){
            return;
        }
        JSONObject data = (JSONObject) jsonObject.get("data");
        jdData.setAccessEnsureNum((Integer) data.get("accessEnsureNum"));
        jdData.setAccessNum((Integer) data.get("accessNum"));
    }

    /**
     * 解析成Java bean
     * @param jsonObject
     * @return
     */
    private static List<JdData> parsingData(JSONObject jsonObject){
        List<JSONObject> property = (List<JSONObject>) jsonObject.get("datas");
        List<JdData> jdDatas = new LinkedList<>();
        if (CollectionUtil.isEmpty(property)){
            return jdDatas;
        }
        property.forEach(map->{
            JdData jdData = JSON.toJavaObject(map,JdData.class);
            jdDatas.add(jdData);
        });
        return jdDatas;
    }

    /**
     * 抓取数据
     * @param url
     * @return
     */
    private static JSONObject requestData(String url) throws IOException {
        Request request = new Request.Builder().url(url)
                .addHeader("accept", "*/*")
                .addHeader("connection", "Keep-Alive")
                .addHeader("contentType", "utf-8")
                .addHeader("accept-language","zh-CN,zh;q=0.9,en;q=0.8")
                .addHeader("cookie","__jdu=15809783057681031157505; shshshfpa=0884a917-087f-2467-f57b-23d24960558b-1581483701; shshshfpb=h2y2xZ8YKZhvVgPUZlI9UYQ%3D%3D; 3AB9D23F7A4B3C9B=25PZKOJ2CJDZMAYJ2GMHVSPVWITOLXBAP3QA6CLK2XRNW6BAGIU6THOAVWMYGUSLXXTX7GVDS2ABMZAU7LV6RAU3GM; mba_muid=15809783057681031157505; shshshfp=efbbce1938df46b4ed4206a9ddf8e288; __jdv=122270672|baidu|-|organic|not set|1582374387540; areaId=22; ipLoc-djd=22-1930-49327-0; RT=\"z=1&dm=jd.com&si=yfd0ujpazmp&ss=k74vj904&sl=0&tt=0&r=0bfa57d2e173fc3acc2eb927facc6619&ul=r9038&hd=r9045\"; __jda=122270672.15809783057681031157505.1580978306.1582868795.1582972039.28; __jdc=122270672; __jdb=122270672.2.15809783057681031157505|28.1582972039")
                .addHeader("referer","https://auction.jd.com/sifa_list.html?childrenCateId=12728")
                .addHeader("sec-fetch-dest","script")
                .addHeader("sec-fetch-mode","no-cors")
                .addHeader("sec-fetch-site","same-site")
                .addHeader("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36")
                .build();
        String content = getResult(request);
        if (StringUtils.isEmpty(content)){
            //递归  直到成功位置
            return requestData(url);
        }
        content = content.substring(content.indexOf("(") + 1 ,content.lastIndexOf(")"));
        return JSONObject.parseObject(content);
    }

}
